<?php

	namespace org\tekuna\framework;

	use \Exception;
	
	use org\tekuna\base\Tekuna;
	
	use org\tekuna\core\context\Context;
	use org\tekuna\core\event\Event;
	use org\tekuna\core\event\AbstractEventListener;
	
	use org\tekuna\framework\request\Request;
	use org\tekuna\framework\request\RequestException;
	use org\tekuna\framework\request\HttpRequestEvent;
	
	use org\tekuna\framework\response\ResponseEvent;
	use org\tekuna\framework\response\http\FourOhFourResponse;
	use org\tekuna\framework\response\http\FiveOhOhResponse;
	
	use org\tekuna\framework\context\ContextProcessor;
	use org\tekuna\framework\component\HttpComponentProcessor;
	use org\tekuna\framework\action\HttpActionProcessor;
	use org\tekuna\framework\action\HttpActionEvent;
	

	class HttpRequestListener extends AbstractEventListener {

		private $objLogger;


		public function __construct() {

			$this -> objLogger = Tekuna :: getLogger(__CLASS__);
		}

		public function handlesEvent(Event $objEvent) {
			
			return $objEvent instanceof HttpRequestEvent;
		}
		
		public function handleEvent(Event $objEvent) {

			$objConP = new ContextProcessor($this -> getApplicationContext());
			
			try {

				// match component
				$objComP = new HttpComponentProcessor($this -> getApplicationContext());
				$objComponentElement = $objComP -> getMatchingHttpComponent();
				$this -> objLogger -> info("matched component for this request: ". trim($objComponentElement -> __toString()));

				// load the context values out of this component
				$objConP -> updateContext($objComponentElement);

				// match action
				$objAP = new HttpActionProcessor($this -> getApplicationContext(), $objComponentElement);
				$objActionElement = $objAP -> getMatchingHttpAction();
				$this -> objLogger -> info("matched action for this request: ". trim($objActionElement -> __toString()));

				// load the context values out of this action
				$objConP -> updateContext($objActionElement);

				// trigger the HttpActionEvent with all URL information inside
				$objActionEvent = new HttpActionEvent($this -> getApplicationContext(), $objComponentElement, $objActionElement);
				$objActionEvent -> setMatchedComponentBaseUrl($objAP -> getMatchedComponentBaseUrl());
				$objActionEvent -> setMatchedActionUrl($objAP -> getMatchedActionUrl());
				$objActionEvent -> setMatchedPattern($objAP -> getMatchedPattern());
				$objActionEvent -> setMatchedRegex($objAP -> getMatchedRegex());
				$objActionEvent -> setMatchedUrlParts($objAP -> getMatchedUrlParts());
				$this -> getApplicationContext() -> getEventManager() -> triggerEvent($objActionEvent);
			}
			catch (RequestDispatchException $objException) {

				// send 404 if Request is not routable
				$objResponse = new FourOhFourResponse($this -> getApplicationContext() -> getRequest());
				$objResponseEvent = new ResponseEvent($objResponse);
				$this -> getApplicationContext() -> getEventManager() -> triggerEvent($objResponseEvent);
			}
			catch (Exception $objException) {
				
				// log the exception
				Tekuna :: logException($objException);
				
				// send 500 when other Exception occured
				$objResponse = new FiveOhOhResponse($this -> getApplicationContext() -> getRequest(), $objException);
				$objResponseEvent = new ResponseEvent($objResponse);
				$this -> getApplicationContext() -> getEventManager() -> triggerEvent($objResponseEvent);
			}
		}
	}